# encoding=utf8
import xuper
import os
import json
import random
import time

# --- 1. 配置信息 ---
NODE_URL = "http://192.168.1.57:37301"
KEYS_DIR = "./keys"
BC_NAME = "xuper"

# --- 2. C++ WebAssembly 合约配置 ---
WASM_CONTRACT_PATH = "./simplestorage-cpp/simplestorage.wasm"
CONTRACT_INIT_ARGS = {}  # C++合约初始化参数

# --- 主程序 ---
def main():
    """
    使用官方 Xuper Python SDK 部署并与 C++ WebAssembly 合约交互。
    """
    # --- 3. 初始化 SDK 并加载用户账户 ---
    print(f"\n--- 正在初始化 SDK 并连接到: {NODE_URL} ---")
    sdk = xuper.XuperSDK(NODE_URL, BC_NAME)

    print(f"--- 正在从 '{KEYS_DIR}' 目录加载用户账户... ---")
    sdk.readkeys(KEYS_DIR)
    print(f"🎉 用户账户加载成功！地址: {sdk.address}")
    
    # 检查主账户余额
    try:
        balance = sdk.balance()
        print(f"主账户当前余额: {balance}")
    except Exception as e:
        print(f"获取余额失败: {e}")

    # --- 4. 准备部署 ---
    # The name MUST be between 4 and 16 characters long.
    contract_name = "SimpleStorage" + str(random.randint(100, 999))
    
    print(f"\n--- 准备部署合约 ---")
    print(f"合约名 (别名): {contract_name} (Length: {len(contract_name)})")

    try:
        # 4.1 使用 sdk.new_account() 创建一个新的常规账户用于部署
        print(f"\n--- 正在创建新的合约宿主账户... ---")
        new_account_address = sdk.new_account()
        print(f"🎉 新的宿主账户创建成功！地址: {new_account_address}")
        sdk.set_account(new_account_address)
        time.sleep(4)

        # 4.2 向新账户转账资金用于部署
        print(f"\n--- 正在向新账户 '{new_account_address}' 转账资金... ---")
        transfer_amount = 1000000000  # 转账 10 亿单位
        
        # 切换回主账户进行转账
        sdk.set_account(sdk.address)
        resp_transfer = sdk.transfer(new_account_address, transfer_amount, "为合约部署准备资金")
        print(f"转账响应: {str(resp_transfer)}")
        print("等待转账确认...")
        time.sleep(6)
        
        # 切换回新账户进行部署
        sdk.set_account(new_account_address)
        
        # 检查新账户余额
        try:
            new_balance = sdk.balance()
            print(f"新账户当前余额: {new_balance}")
        except Exception as e:
            print(f"获取新账户余额失败: {e}")
            
        print(f"\n--- 现在开始部署合约到 '{new_account_address}' ---")

        # --- 5. 部署 C++ WebAssembly 合约 ---
        print(f"\n--- 正在部署 C++ WASM 合约 '{contract_name}'... ---")
        print("deploying......")
        
        # 使用简化的部署方式
        resp_deploy = sdk.deploy(new_account_address, contract_name, 
                               open(WASM_CONTRACT_PATH, 'rb').read(), 
                               {'creator': b'xuper'})
        
        print("\n🎉 合约部署交易已提交! 🎉")
        print("="*30)
        print("部署响应:")
        # 处理响应中的bytes类型数据
        try:
            # 将bytes转换为字符串以便JSON序列化
            resp_str = str(resp_deploy)
            print(resp_str)
        except Exception as e:
            print(f"响应格式化失败: {e}")
            print(f"原始响应类型: {type(resp_deploy)}")
        print("="*30)
        
        # 检查部署是否成功
        if hasattr(resp_deploy, 'txid') and resp_deploy.txid:
            print(f"✅ 合约 '{contract_name}' 部署成功! TxID: {resp_deploy.txid}")
        else:
            raise Exception(f"合约部署失败: 未获取到有效的交易ID")
        print("请等待几秒钟，让交易上链确认...")
        time.sleep(6)

        # --- 6. 与已部署的 C++ WASM 合约交互 ---
        
        # 注意：C++合约在部署时已经自动调用了initialize方法
        print(f"\n--- 合约已初始化，开始测试功能... ---")
        
        # 6.1 调用 set 方法
        print(f"\n--- 正在调用 '{contract_name}.set(\"name\", \"XuperChain\")... ---")
        set_args = {"key": b"name", "value": b"XuperChain"}  # 使用字节类型
        resp_set = sdk.invoke(contract_name, "set", set_args)
        print("Invoke 'set' 响应:", str(resp_set))
        print("请再次等待几秒钟...")
        time.sleep(6)

        # 6.2 调用 get 方法
        print(f"\n--- 正在查询 '{contract_name}.get(\"name\")... ---")
        get_args = {"key": b"name"}  # 使用字节类型
        resp_get = sdk.preexec(contract_name, "get", get_args)
        
        print("\n🎉 查询成功! 🎉")
        print(f"查询结果: {resp_get}")
        
        # 解析查询结果
        try:
            import json
            import base64
            if isinstance(resp_get, bytes):
                resp_json = json.loads(resp_get.decode('utf-8'))
                if 'response' in resp_json and 'response' in resp_json['response']:
                    responses = resp_json['response']['response']
                    if responses and len(responses) > 0:
                        # 解码base64结果
                        encoded_value = responses[0]
                        decoded_value = base64.b64decode(encoded_value).decode('utf-8')
                        print(f"\n📋 解析后的值: {decoded_value}")
                        print(f"\n✅ 完整测试成功！")
                        print(f"   - 合约部署: ✅")
                        print(f"   - 数据存储: ✅")
                        print(f"   - 数据查询: ✅")
                        print(f"   - 存储的键值对: name = {decoded_value}")
        except Exception as e:
            print(f"解析结果时出错: {e}")
            print("但合约功能测试已成功完成！")
        
    except Exception as e:
        print(f"\n❌ 操作失败: {e}")


if __name__ == "__main__":
    main()